﻿
using System;
using System.Diagnostics;
using My.Ioc;

namespace ConstructorSelectAndParameterOverride
{
    #region Test Types

    public class ParameterClass1
    {
    }
    public class ParameterClass2
    {
    }
    public class ParameterClass3
    {
    }
    public class ParameterClass4
    {
    }
    public class ParameterClass5
    {
    }
    public class PositionalTarget
    {
        private ParameterClass1 _c1;
        private ParameterClass2 _c2;
        private ParameterClass3 _c3;
        private ParameterClass4 _c4;
        private ParameterClass5 _c5;
        private int _age;
        private string _name;

        public PositionalTarget(ParameterClass1 c1, int age, string name, ParameterClass2 c2, ParameterClass3 c3, ParameterClass4 c4)
        {
            _c1 = c1;
            _c2 = c2;
            _c3 = c3;
            _c4 = c4;
            _name = name;
            _age = age;
        }

        public PositionalTarget(ParameterClass1 c1, int age, string name, ParameterClass5 c5, ParameterClass3 c3, ParameterClass4 c4)
        {
            _c1 = c1;
            _c5 = c5;
            _c3 = c3;
            _c4 = c4;
            _name = name;
            _age = age;
        }

        public ParameterClass5 ParameterClass5
        {
            get { return _c5; }
        }

        public ParameterClass2 ParameterClass2
        {
            get { return _c2; }
        }

        public string Name
        {
            get { return _name; }
        }

        public int Age
        {
            get { return _age; }
        }
    }
    public class NamedTarget
    {
        private ParameterClass1 _c1;
        private ParameterClass2 _c2;
        private ParameterClass3 _c3;
        private ParameterClass4 _c4;
        private ParameterClass5 _c5;
        private int _age;
        private string _name;

        public NamedTarget(ParameterClass1 c1, int age, ParameterClass2 c2, ParameterClass3 c3, string name, ParameterClass4 c4)
        {
            _c1 = c1;
            _c2 = c2;
            _c3 = c3;
            _c4 = c4;
            _name = name;
            _age = age;
        }

        public NamedTarget(ParameterClass1 c1, int age, ParameterClass5 c5, ParameterClass3 c3, ParameterClass4 c4)
        {
            _c1 = c1;
            _c5 = c5;
            _c3 = c3;
            _c4 = c4;
            _age = age;
        }

        public ParameterClass5 ParameterClass5
        {
            get { return _c5; }
        }

        public ParameterClass2 ParameterClass2
        {
            get { return _c2; }
        }

        public string Name
        {
            get { return _name; }
        }

        public int Age
        {
            get { return _age; }
        }
    }

    #endregion

    class Program
    {
        static void Main(string[] args)
        {
            IObjectContainer container = new ObjectContainer(false);
            Register(container);

            ResolvePositionalTargetWithoutOverridingParameters(container);
            ResolvePositionalTargetAndOverrideWithPositionalParameters(container);
            ResolvePositionalTargetAndOverrideWithNamedParameters(container);

            ResolveNamedTargetWithoutOverridingParameters(container);
            ResolveNamedTargetAndOverrideWithPositionalParameters(container);
            ResolveNamedTargetAndOverrideWithNamedParameters(container);

            Console.ReadLine();
        }

        static void Register(IObjectContainer container)
        {
            container.Register<ParameterClass1>();
            container.Register<ParameterClass2>();
            container.Register<ParameterClass3>();
            container.Register<ParameterClass4>();
            container.Register<ParameterClass5>();

            container.Register<PositionalTarget>()
                .WithConstructor(
                Parameter.Auto,
                Parameter.Positional(30),
                Parameter.Positional("China"),
                Parameter.Positional<ParameterClass5>());

            container.Register<NamedTarget>()
                .WithConstructor(Parameter.Named("age", 90));

            container.CommitRegistrations();
        }

        static void ResolvePositionalTargetWithoutOverridingParameters(IObjectContainer container)
        {
            Console.WriteLine("Resolve PositionalTarget without overriding default parameters: ");

            var positional = container.Resolve<PositionalTarget>();
            Debug.Assert(positional.ParameterClass5 != null);
            Console.WriteLine(positional.Name);
            Console.WriteLine(positional.Age);
        }

        static void ResolvePositionalTargetAndOverrideWithPositionalParameters(IObjectContainer container)
        {
            Console.WriteLine("Resolve PositionalTarget and override default parameters using positional parameters: ");

            var positional = container.Resolve<PositionalTarget>(
                Parameter.Auto,
                Parameter.Positional(99),
                Parameter.Positional("ZhongHua"));
            Debug.Assert(positional.ParameterClass5 != null);
            Console.WriteLine(positional.Name);
            Console.WriteLine(positional.Age);
        }

        static void ResolvePositionalTargetAndOverrideWithNamedParameters(IObjectContainer container)
        {
            Console.WriteLine("Resolve PositionalTarget and override default parameters using named parameters: ");

            var positional = container.Resolve<PositionalTarget>(
                Parameter.Named("name", "HuaXia"));
            Debug.Assert(positional.ParameterClass5 != null);
            Console.WriteLine(positional.Name);
            Console.WriteLine(positional.Age);
        }


        static void ResolveNamedTargetWithoutOverridingParameters(IObjectContainer container)
        {
            Console.WriteLine("Resolve NamedTarget without overriding default parameters: ");

            var named = container.Resolve<NamedTarget>();
            Debug.Assert(named.ParameterClass5 != null);
            Debug.Assert(named.Name == null);
            Console.WriteLine(named.Age);
        }

        static void ResolveNamedTargetAndOverrideWithPositionalParameters(IObjectContainer container)
        {
            Console.WriteLine("Resolve NamedTarget and override default parameters using positional parameters: ");

            var named = container.Resolve<NamedTarget>(
                Parameter.Auto,
                Parameter.Positional(12));
            Debug.Assert(named.ParameterClass5 != null);
            Debug.Assert(named.Name == null);
            Console.WriteLine(named.Age);
        }

        static void ResolveNamedTargetAndOverrideWithNamedParameters(IObjectContainer container)
        {
            Console.WriteLine("Resolve NamedTarget and override default parameters using named parameters: ");

            var named = container.Resolve<NamedTarget>(
                Parameter.Named("age", 68));
            Debug.Assert(named.ParameterClass5 != null);
            Debug.Assert(named.Name == null);
            Console.WriteLine(named.Age);
        }
    }
}
